<?php

/*

http://wiki.hydrogenaudio.org/index.php?title=Foobar2000:ID3_Tag_Mapping

Field Name1 	 ID3v2.3 Frame 	 ID3v2.4 Frame 	 Description 	 Comments 
ALBUM 	 TALB 	 TALB 	 Album/Movie/Show title 	
ARTIST 	TPE1 	TPE1 	Lead performer(s)/Soloist(s) 	
ARTIST WEBPAGE URL 	WOAR 	WOAR 	Official artist/performer webpage 	
BAND 	TPE2 	TPE2 	Band/orchestra/accompaniment 	
BPM 	TBPM 	TBPM 	BPM (beats per minute) 	
COMMENT 	COMM 	COMM 	Comments 	
COMMERCIAL INFORMATION URL 	WCOM 	WCOM 	Commercial information 	
COMPOSER 	TCOM 	TCOM 	Composer 	
CONDUCTOR 	TPE3 	TPE3 	Conductor/performer refinement 	
CONTENT GROUP 	TIT1 	TIT1 	Content group description 	
COPYRIGHT 	TCOP 	TCOP 	Copyright message 	
DATE 		TDRC 	Recording time 	The TDRC frame is officially to be used for the recording time, TDRL is for the release time but TDRC is generally used by most programs.
DATE 	TYER 		Year 	
DISCNUMBER 	TPOS 	TPOS 	Part of a set 	
ENCODED BY 	TENC 	TENC 	Encoded by 	
ENCODING SETTINGS 	TSSE 	TSSE 	Software/Hardware and settings used for encoding 	
FILE WEBPAGE URL 	WOAF 	WOAF 	Official audio file webpage 	
GENRE 	TCON 	TCON 	Content type 	
INTERNET RADIO WEBPAGE URL 	WORS 	WORS 	Official Internet radio station homepage 	
ISRC 	TSRC 	TSRC 	ISRC (international standard recording code) 	
ORIGINAL ALBUM 	TOAL 	TOAL 	Original album/movie/show title 	
ORIGINAL ARTIST 	TOPE 	TOPE 	Original artist(s)/performer(s) 	
ORIGINAL RELEASE DATE 		TDOR 	Original release time 	
ORIGINAL RELEASE DATE 	TORY 		Original release year 	
OWNER 	TOWN 	TOWN 	File owner/licensee 	
PAYMEMT URL 	WPAY 	WPAY 	Payment 	
PUBLISHER 	TPUB 	TPUB 	Publisher 	
PUBLISHER URL 	WPUB 	WPUB 	Publishers official webpage 	
RADIO STATION 	TRSN 	TRSN 	Internet radio station name 	
REMIXED BY 	TPE4 	TPE4 	Interpreted, remixed, or otherwise modified by 	
SOURCE WEBPAGE URL 	WOAS 	WOAS 	Official audio source webpage 	
SUBTITLE 	TIT3 	TIT3 	Subtitle/Description refinement 	
TITLE 	TIT2 	TIT2 	Title/songname/content description 	
TRACKNUMBER 	TRCK 	TRCK 	Track number/Position in set 	
TOTALDISCS 	TPOS 	TPOS 	Part of a set 	Stored in the same frame with DISCNUMBER, separated by '/': e.g. '1/2'. Stored in TXXX if DISCNUMBER does not exist.
TOTALTRACKS 	TRCK 	TRCK 	Total tracks 	Stored in the same frame with TRACKNUMBER, separated by '/': e.g. '4/9'. Stored in TXXX if TRACKNUMBER doesn't exist.
UNSYNCED LYRICS 	USLT 	USLT 	Unsynchronised lyric/text transcription 	
WRITER 	TEXT 	TEXT 	Lyricist/Text writer 
*/


function getId3Tags($files, $tags = null)
{
	/* Get all ID3 in files */
	$data = array(
		'WITH_ID3' => array(),
		'NO_ID3' => array()
	);
	foreach ($files as $file)
	{
		try {
				if(!is_null($tags))
				{
					$file_tags = array();
					$id3 = new ID3v2($file);
					
					foreach ($tags as $tag)
					{
						$frame = $id3->getFramesByIdentifier($tag);
						$content = $frame[0]->getText();
						/*
						$frame = $id3->getFramesByIdentifier("APIC"); // for attached picture
						$image = $frame[0]->getImageType();
						*/
						//wash a lil bit...
						if(strlen($content) != 0 && $content != 'Inconnu' && !($content == '0' && $frame->identifier == 'TRCK') && !($content == '0' && $frame->identifier == 'TPOS') )
							$data['WITH_ID3'][$file]['USEFUL'][$tag] = $content;
						else
							$data['WITH_ID3'][$file]['USELESS'][$tag] = $content;
					}
				}
				else
				{
					$id3 = new ID3v2($file);
					foreach ($id3->frames as $frames) {
						foreach ($frames as $frame) {
							$content = null;
							if ($frame instanceof ID3_Frame_AbstractText)
								$content = $frame->text;
							if ($frame instanceof ID3_Frame_AbstractLink)
								$content = $frame->link;
							if ($frame instanceof ID3_Frame_APIC)
								$content = $frame->imageType;
					
							//wash a lil bit...
							if(strlen($content) != 0 && $content != 'Inconnu' && !($content == '0' && $frame->identifier == 'TRCK') && !($content == '0' && $frame->identifier == 'TPOS') )
								$data['WITH_ID3'][$file]['USEFUL'][$frame->identifier] = $content;
							else
								$data['WITH_ID3'][$file]['USELESS'][$frame->identifier] = $content;
						}
					}
				}
				
		}
		catch (ID3_Exception $e) {
				$data['NO_ID3'][$file] = $e->getMessage();
				continue;
		}
	}
	
	/* get useful tags */
	$usefulTags = array();
	foreach ($data['WITH_ID3'] as $file)
	{
		foreach ($file['USEFUL'] as $tagName => $tagValue)
		{
			if(!isset($usefulTags[$tagName]))
				$usefulTags[$tagName] = 0;
			else
				$usefulTags[$tagName]++;
		}
	}
	return array('data' => $data, 'usefulTags' => $usefulTags);
}

function getHumanId3Tag($key) {
	global $tagProperties;
	return isset($tagProperties[$key]) ? $tagProperties[$key] : array('name' => $key,'width' => '10');
}

function getListingData($subdir)
{
	global $currentStep, $steps;
		$tracks_tmp = $steps[$currentStep['name']]['tracks'];
		
		$tracks = array();
		foreach($tracks_tmp as $track)
		{
			if (strpos($track, $steps[$currentStep['name']]['dir'].$subdir) !== false)
				$tracks[] = $track;
		}
	/* get id3 data */
	if (array_search('all_tags', $steps[$currentStep['name']]['columns']) !== false)
		$id3tags = getId3Tags($tracks);
	else
		$id3tags = getId3Tags($tracks, $steps[$currentStep['name']]['tag_columns']);
	$data = $id3tags['data'];

	/* convert data for listing structure */
	$songs = array(
		'settings' => array(
			'column_with_id' => 'id',
			'editable' => false,
			'removable' => false,
			'viewable' => false,
			'multiple_action' => true,
			'columns' => array(
				'id' => array(
					'displayed' => false
				),
				'filename' => array(
					'title' => 'Filename ('.count($steps[$currentStep['name']]['tracks']).', '.count($data['NO_ID3']).' without tags)',
					'displayed' => true,
					'filterable' => false,
					'sortable' => true,
					'editable' => false,
					'href' => '#',
					'html' => '<img src="'._kmm_fff_uri_.'/control_play.png" style="vertical-align:-3px;" alt="" />',
					'onclick' => 'return playTrack($(this).parent().parent());'
				),
				'file_uri' => array(
					'hidden' => true,
					'displayed' => true,
					'filterable' => false,
					'sortable' => false,
					'editable' => false,
					'width_in_percent' => 11
				),
				'title' => array(
					'title' => 'Title',
					'displayed' => true,
					'filterable' => true,
					'sortable' => true,
					'editable' => true,
					'width_in_percent' => 18,
					'class' => 'tag_TIT2'
				),
				'artist' => array(
					'title' => 'Artist',
					'displayed' => true,
					'filterable' => true,
					'sortable' => true,
					'editable' => true,
					'width_in_percent' => 15,
					'class' => 'tag_TPE1'
				),
				'album' => array(
					'title' => 'Album',
					'displayed' => true,
					'filterable' => true,
					'sortable' => true,
					'editable' => true,
					'width_in_percent' => 15,
					'class' => 'tag_TALB'
				),
				'track_number' => array(
					'title' => 'Track #',
					'displayed' => true,
					'filterable' => false,
					'sortable' => false,
					'editable' => true,
					'width_in_percent' => 4,
					'class' => 'tag_TRCK'
				),
				'genre' => array(
					'title' => 'Genre',
					'displayed' => true,
					'filterable' => true,
					'sortable' => true,
					'editable' => true,
					'width_in_percent' => 11,
					'class' => 'tag_TCON'
				),
				'valid' => array(
					'displayed' => true,
					'filterable' => false,
					'sortable' => false,
					'editable' => false,
					'width_in_percent' => 2,
					'html' => '<img src="'._kmm_fff_uri_.'/arrow_right.png" alt="Valid !!" />',
					'href' => '#',
					'onclick' => 'return moveToTheNextStep($(this).parent().parent());'
				)
			)
		)
	);
	foreach ($data['WITH_ID3'] as $filename => $with_id3)
	{
		$line = array ();
		$line['id'] = md5($filename);
		$line['file_uri'] = _dir_to_uri($filename);
		$line['filename'] = str_replace($currentStep['dir'].'/', '', $filename);
		$line['title'] = $with_id3['USEFUL']['TIT2'];
		$line['artist'] = $with_id3['USEFUL']['TPE1'];
		$line['album'] = $with_id3['USEFUL']['TALB'];
		$line['track_number'] = $with_id3['USEFUL']['TRCK'];
		$line['total_tracks'] = $with_id3['USEFUL']['TRCK'];
		$line['genre'] = $with_id3['USEFUL']['TCON'];
		$line['valid'] = '';
		$songs['content'][] = $line;
	}
	return $songs;
}

function move_a_file_to_the_next_step($currentStepName, $filename)
{
	if (file_exists($filename))
	{
		$nextStep = _getNextStep($currentStepName);
		if ($nextStep === false)
		{
			echo 'error: no more step for this song, it\'s clean now !';
			return false;
		}
		
		$newFilename = str_replace(dirname($filename) , $nextStep , $filename);
		if (rename($filename, $newFilename))
		{
			return true;
		}
		else
		{
			echo 'error: unable to move this file...';
			return false;
		}
	}
	else echo 'error: file ' . $filename . ' is not found...';
	return false;
}

function _dir_to_uri($dir){
	return str_replace(_kmm_base_dir_, _kmm_base_uri_, $dir);
}

function _uri_to_dir($uri){
	return str_replace(_kmm_base_uri_, _kmm_base_dir_, $uri);
}

function _display_error($message){
	global $ajax_mode;
	if (!$ajax_mode)
		echo '<p style="color:red;">ERROR: '.$message.'</p>';
	die;
}

function _display_warning($message){
	global $ajax_mode;
	if (!$ajax_mode)
		echo '<p style="color:orange;">WARNING: '.$message.'</p>';
}

function wash($value){
	return htmlentities($value,ENT_COMPAT,'UTF-8');
}

function _is_readable($dir, $recursive = false)
{
	if (!is_readable($dir) OR !$dh = opendir($dir))
		return false;
	if ($recursive)
	{
		while (($file = readdir($dh)) !== false)
			if (@filetype($dir.$file) == 'dir' AND $file != '.' AND $file != '..')
				if (!_is_readable($dir.$file, true))
					return false;
	}
	closedir($dh);
	return true;
}

function _is_writable($dir, $recursive = false)
{
	if (!is_writable($dir) OR !$dh = opendir($dir))
		return false;
	if ($recursive)
	{
		while (($file = readdir($dh)) !== false)
			if (@filetype($dir.$file) == 'dir' AND $file != '.' AND $file != '..')
				if (!_is_writable($dir.$file, true))
					return false;
	}
	closedir($dh);
	return true;
}
function _getNextStep($currentStepName)
{
	global $steps;
	$endStep = end($steps);
	if ($currentStepName != $endStep['name'])
	{
		foreach ($steps as $key => $step)
		{
			if ($key == $currentStepName)
			{
				$nextStep = current($steps);
				return $steps[$nextStep['name']]['dir'];
			}
		}
	}
	return false;
}

function _getFileNameFromMd5($stepName, $md5)
{
	global $steps;
	$tracks = $steps[$stepName]['tracks'];
	$filename = false;
	foreach ($tracks as $track)
		if (md5($track) == $md5)
		{
			$filename = $track;
			break;
		}
	return $filename;
}

function _escape_accents($value)
{
	return strtr(
		utf8_decode($value),
		utf8_decode("ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÌÍÎÏìíîïÙÚÛÜùúûüÿÑñÇç'"),
		utf8_decode("AAAAAAaaaaaaOOOOOOooooooEEEEeeeeIIIIiiiiUUUUuuuuyNnCc ")
	);
}

function _scanDirectories($dir, $allowext, &$allData = array()) {
	$dirContent = scandir($dir);
	foreach($dirContent as $key => $content) {
		if ($content == '.' || $content == '..') continue;
		$path = $dir . DIRECTORY_SEPARATOR . $content;
		$ext = substr($content, strrpos($content, '.') + 1);
		if (in_array($ext, $allowext) && is_file($path) && is_readable($path)) {
			if (mime_content_type($path) == 'audio/mpeg')
				$allData[] = $path;
			else
				_display_warning('mimetype of '.$path.' is not audio/mpeg so this file will be ignored.');
		}
	else if(is_dir($path) && is_readable($path)) {
		// recursive callback to open new directory
		_scanDirectories($path, $allowext, $allData);
	}
	// else unreadable hell
	}
	return $allData;
}

function _getRequestParameter($key, $defaultValue = false)
{
	global $cookie;

 	if (!isset($key) OR empty($key) OR !is_string($key))
		return false;
	$ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $defaultValue));

	if (is_string($ret) === true)
		$ret = urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret)));

	return is_array($ret) ? $ret : stripslashes($ret);
}


function _p($var){
	echo '<pre>';
	print_r($var);
	echo '</pre>';
}

function _d($var){
	_p($var);
	die;
}
